IIFE(Immediately Invoked Function Expression),是一種「可以立即執行的函式」。
一般的函式長這樣:
function doSomething (x){
//do something
};
doSomething(參數); //呼叫doSomething,執行程式區塊
而立即執行函式長成這個樣子:
(function doSomething (x) {
//do something
})(參數); //不用呼叫doSomething函式,X帶入參數,立即在程式區塊中執行
立即執行函式,不透過呼叫函式的方式,瀏覽器讀到函式後面附加的小括號( ),就知道要在函式宣告的當下立即執行。
假設洪七公嘴饞想吃叫化雞,叫黃蓉馬上烤一隻叫化雞來吃:
(function cooking(food){
console.log(`丫頭去弄個${food}來吃吃!!!`);
})('叫化雞') //丫頭去弄個叫化雞來吃吃!!!
cooking('東坡肉'); //Uncaught ReferenceError: cooking is not defined
如果在立即執行函式的外面再呼叫一次cooking函式,就會出現「Uncaught ReferenceError: cooking is not defined」。
既然提到了立即執行函式,讓我們利用它來解一下面試中常常會出現的考題:
「每次間隔一秒,依次印出0、1、2、3、4」
你會怎麼解呢?直覺應該利用for迴圈 + window.setTimeout()來解題:
for(var i = 0; i < 5; i++){
window.setTimeout(function(){
console.log(i);
},1000)
}
圖
結果是直接印出五個5,說好的0、1、2、3、4呢?
還記得前面提過「切分辨數最小範圍是function」,所以for迴圈和window.setTimeout()是個跑各的。
for迴圈是急驚風,而window.setTimeout()是慢郎中,window.setTimeout()剛剛過了一秒去捉外面的i來console.log()的時候,for迴圈已經跑完五次,i++變成5,不符合i<5的條件跳出迴圈了,所以window.setTimeout()捉迴圈的i,每次都捉到5。
那要怎麼解決這個問題呢? 我們可以把window.setTimeout()封裝在一個立即執行函式裡面,後面的小括號則帶入迴圈每次跑出來的 i,讓 i 把值帶入 x 裡面丟到 window.setTimeout() 去執行。
for(var i = 0; i < 5; i++){
(function(x){
window.setTimeout(function(){
console.log(x);
},x*1000);
})(i);
}
這樣就會每隔1秒依序印出0、1、2、3、4了。
當然另外一個更簡單的解法則是把for迴圈的變數宣告「var i = 0」直接改成「let i = 0」,利用let是以大括號區塊為作用域的概念,讓for迴圈必須與window.setTimeout()一起跑。
for(let i = 0; i < 5; i++){
window.setTimeout(function(){
console.log(i);
},1000)
}
這樣就會間格1秒,依序印出0、1、2、3、4了。